import java.io.File;
import java.io.IOException;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import java.util.HashMap;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.google.api.translate.Language;
import com.google.api.translate.Translate;

public class Translator {
	public static final String STRING="string";
	public static final String NAME="name";

	public static Map<Language,String> languageMap = new HashMap<Language,String>();
	static {
		// ACTION add or remove whatever languages you want to translate to
//		languageMap.put(Language.ENGLISH, "");
		languageMap.put(Language.FRENCH, "-fr");
		languageMap.put(Language.JAPANESE, "-ja");
		languageMap.put(Language.GERMAN, "-de");
		languageMap.put(Language.SPANISH, "-es");
		languageMap.put(Language.ITALIAN, "-it");
		languageMap.put(Language.DUTCH, "-nl");
		languageMap.put(Language.AFRIKAANS, "-za");
	}

	public static Document loadDocument(File d) throws ParserConfigurationException, SAXException, IOException {
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = dbf.newDocumentBuilder();
		if (d.exists()) {
			Document doc = db.parse(d);
			return doc;
		}
		else {
			Document doc = db.newDocument();
			Element rootElement = doc.createElement("resources");
			doc.appendChild(rootElement);
			return doc;
		}
	}

	public static String getStringResource(Document doc, String nameElement) {
		try {
			NodeList nodeLst = doc.getElementsByTagName(STRING);

			for (int s = 0; s < nodeLst.getLength(); s++) {
				Node fstNode = nodeLst.item(s);
				String nameKey = fstNode.getAttributes().getNamedItem("name").getNodeValue();
				if (nameElement.equals(nameKey)) {
					return fstNode.getTextContent();
				}
			}
		}
		catch (Throwable t) {
			return null;
		}
		return null;
	}

	public static void setStringResource(Document doc, String nameElement, String value) {
		try {
			NodeList nodeLst = doc.getElementsByTagName(STRING);

			for (int s = 0; s < nodeLst.getLength(); s++) {
				Node fstNode = nodeLst.item(s);
				String nameKey = fstNode.getAttributes().getNamedItem("name").getNodeValue();
				if (nameElement.equals(nameKey)) {
					fstNode.setTextContent(value);
					return;
				}
			}

			// no existing element found, create a new one
			Element newNameElement = doc.createElement(STRING);
			newNameElement.setAttribute("name", nameElement);
			newNameElement.appendChild(doc.createTextNode(forXML(value)));
			doc.getDocumentElement().appendChild(newNameElement);
		}
		catch (Throwable t) {
			t.printStackTrace();
		}
	}

	public static void TranslateSoft(File src, File dest, Language sourceL, Language destL) throws Exception {
		// ACTION Set the HTTP referrer to your website address.
		Translate.setHttpReferrer("http://google.com");

		try {
			Document doc = loadDocument(src);
			Document translatedDoc = loadDocument(dest);

			doc.getDocumentElement().normalize();

			NodeList nodeLst = doc.getElementsByTagName(STRING);

			for (int s = 0; s < nodeLst.getLength(); s++) {
				Node fstNode = nodeLst.item(s);
				String resourceName = fstNode.getAttributes().getNamedItem(NAME).getNodeValue();
				try {
					String translated;
					if ((translated=getStringResource(translatedDoc,resourceName))==null) {
						translated = Translate.execute(fstNode.getTextContent(), sourceL, destL);
						System.out.println("Translated "+resourceName+"="+translated);
					}
					else {
						System.out.println("Skipping "+resourceName+"="+translated);
					}
					setStringResource(translatedDoc,resourceName,translated);
				}
				catch (Exception e) {
					// on exception put the original text in
					setStringResource(translatedDoc,resourceName,fstNode.getTextContent());
				}
			}
			//write the content into xml file
			TransformerFactory transformerFactory = TransformerFactory.newInstance();
			Transformer transformer = transformerFactory.newTransformer();
			transformer.setOutputProperty(OutputKeys.INDENT, "yes");
			transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
			DOMSource source = new DOMSource(translatedDoc);
			StreamResult result =  new StreamResult(dest);
			transformer.transform(source, result);
		} 
		catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static String forXML(String aText){
		final StringBuilder result = new StringBuilder();
		final StringCharacterIterator iterator = new StringCharacterIterator(aText);
		char character =  iterator.current();
		while (character != CharacterIterator.DONE ){
			if (character == '<') {
				result.append("&lt;");
			}
			else if (character == '>') {
				result.append("&gt;");
			}
			else if (character == '\"') {
				result.append("\\\"");
			}
			else if (character == '\'') {
				result.append("\\'");
			}
			else if (character == '&') {
				result.append("&amp;");
			}
			else {
				//the char is not a special one
				//add it to the result as is
				result.append(character);
			}
			character = iterator.next();
		}
		return result.toString();
	}



	private static void addAttributes(NamedNodeMap attributes,	Element nameElement) {
		for (int i = 0; i < attributes.getLength(); i++) {
			Node a = attributes.item(i);
			nameElement.setAttribute(a.getNodeName(), a.getNodeValue());
		}
	}

	public static void main(String[] args) throws Exception {
		// ACTION edit the location of the resource file to translate
		String srcResourceFile = "~/workspace/????/res/values/strings.xml";//"C:/workspaces/workspace.galileo/????/res/values/strings.xml";
		// ACTION specify the source language of the file to translate
		Language srcLanguage = Language.ENGLISH;

		File src = new File(srcResourceFile);
		File destDir, dest;
		for (Language destLanguage : languageMap.keySet()) {
			if (destLanguage!=srcLanguage) {
				destDir = new File(src.getParentFile().getParentFile().getCanonicalPath()+File.separator+"values"+languageMap.get(destLanguage));
				destDir.mkdirs();
				dest = new File(src.getParentFile().getParentFile().getCanonicalPath()+File.separator+"values"+languageMap.get(destLanguage)+File.separator+"strings.xml");
				System.out.println("Creating file :"+dest.getCanonicalPath());
				TranslateSoft(src, dest, srcLanguage, destLanguage);
			}
		}

	}
}
